package com.sso.oa.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * OA 系统安全配置
 * 
 * @author SSO System
 * @since 2024-01-01
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    private final ClientRegistrationRepository clientRegistrationRepository;
    
    @Autowired
    private OidcUserService oidcUserService;

    public SecurityConfig(ClientRegistrationRepository clientRegistrationRepository) {
        this.clientRegistrationRepository = clientRegistrationRepository;
    }

    /**
     * OAuth2授权请求仓库
     * 解决authorization_request_not_found错误
     */
    @Bean
    public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
        return new HttpSessionOAuth2AuthorizationRequestRepository();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable()) // 禁用CSRF以避免干扰OAuth2流程
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/", "/login", "/error", "/webjars/**", "/css/**", "/js/**", "/images/**").permitAll()
                        .requestMatchers("/api/public/**").permitAll()
                        .requestMatchers("/sso", "/api/validate-token").permitAll() // 允许单点登录请求
                        .anyRequest().authenticated()
                )
                .oauth2Login(oauth2Login -> oauth2Login
                        .loginPage("/login")
                        .authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint
                                .authorizationRequestRepository(authorizationRequestRepository())
                        )
                        .successHandler(oauth2LoginSuccessHandler())
                        .failureHandler(oauth2LoginFailureHandler())
                        .userInfoEndpoint(userInfo -> userInfo
                                .oidcUserService(oidcUserService)
                        )
                )
                .oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer
                        .jwt(jwt -> jwt
                                .jwkSetUri("http://www.oauth2server.com:9000/.well-known/jwks.json")
                        )
                )
                .logout(logout -> logout
                        .logoutSuccessHandler(oidcLogoutSuccessHandler())
                        .invalidateHttpSession(true)
                        .clearAuthentication(true)
                        .deleteCookies("JSESSIONID")
                );

        return http.build();
    }

    /**
     * OAuth2 登录成功处理器
     * 根据项目规范实现智能路由跳转
     */
    private SimpleUrlAuthenticationSuccessHandler oauth2LoginSuccessHandler() {
        return new SimpleUrlAuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, 
                                              HttpServletResponse response, 
                                              Authentication authentication) 
                    throws IOException, ServletException {
                System.out.println("OAuth2 登录成功: " + authentication.getName());
                System.out.println("用户权限: " + authentication.getAuthorities());
                // 登录成功后跳转到首页
                setDefaultTargetUrl("/");
                setAlwaysUseDefaultTargetUrl(true);
                super.onAuthenticationSuccess(request, response, authentication);
            }
        };
    }
    
    /**
     * OAuth2 登录失败处理器
     */
    private SimpleUrlAuthenticationFailureHandler oauth2LoginFailureHandler() {
        return new SimpleUrlAuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest request, 
                                              HttpServletResponse response, 
                                              AuthenticationException exception) 
                    throws IOException, ServletException {
                System.err.println("OAuth2 登录失败: " + exception.getMessage());
                exception.printStackTrace();
                super.onAuthenticationFailure(request, response, exception);
            }
        };
    }

    /**
     * OIDC 登出成功处理器
     */
    private LogoutSuccessHandler oidcLogoutSuccessHandler() {
        OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler =
                new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);

        // 设置登出后重定向的 URI
        oidcLogoutSuccessHandler.setPostLogoutRedirectUri("http://www.oauth2server.com:8080/");

        return oidcLogoutSuccessHandler;
    }
} 